Skip to content

feat: parse Q10 archived map packets - #936

Merged
allenporter merged 8 commits into
Python-roborock:mainfrom
hCoureau:feat/q10-archive-packets
Sep 27, 2026
Merged

allenporter merged 8 commits into
Python-roborock:mainfrom
hCoureau:feat/q10-archive-packets

Conversation

@hCoureau

@hCoureau hCoureau commented Aug 31, 2026 •

Copy link
Copy Markdown
Contributor

Q10 clean-record and saved-map responses use different packet markers from live maps. This adds bounded archive parsing and a Q10CleanRecordDetail(map, trace) response so callers receive a map and its historical path together without extending the map raster model.

Implementation

  • Q10MapPacketKind classifies current, live-trace, clean-record, and saved-map markers. Unknown markers are ignored rather than treated as current maps.
  • Shared raster fields are decoded once. Clean-record responses compose a Q10MapPacket with an optional Q10HistoricalTracePacket.
  • Historical traces expose points and heading. Version and reserved fields are validated inside the parser; undecoded framing is kept out of the public model.
  • Historical paths use the same conservative stray-leading-point filter as live paths. Short paths and ordinary origin points are preserved.
  • Rendering consumes the explicitly supplied map and trace without type-dependent branching or ignored arguments.
  • Decompression requires an output bound. Unused marker/carpet helpers and unused trace return data are removed.

#937 consumes the composed response in its archive traits. This PR provides parser and renderer support; archive request lifecycle handling belongs to #937.

Dependencies

#933, #908, and #965 are merged. No instruction to merge #965 first remains applicable. Upstream main through d967baf is integrated.

Validation and limits

Validation of 3d3a337:

  • uv run pytest -q on Python 3.13: 1,415 passed, 53 xfailed, 92 snapshots passed.
  • All pre-commit hooks passed, including Ruff, mypy, codespell, and structured-file checks.
  • uv build passed for both wheel and sdist.
  • The full cumulative feat: add Q10 customized cleaning controls #935 suite, which includes these changes, also passed on Python 3.11 and 3.14.

No physical-device run was performed for this revision.

Coverage includes unknown/truncated markers, unsupported archive framing, malformed paths, stray-point filtering, and explicit historical-path rendering. Unsupported historical-path framing remains undecoded; a parsed map may therefore have no historical trace.

No private map captures or account data are included. Related: #767.

Comment thread roborock/map/b01_q10_map_parser.py Outdated

@allenporter allenporter left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am very happy to keep momentum going on this. I am adding additional feedback since this hasn't been moving since my last comment, in case it was missed. I have a lot of time to review during the us holidy weekend.

Comment thread roborock/protocols/b01_q10_protocol.py Outdated
Comment thread roborock/map/b01_q10_map_parser.py Outdated
Comment thread roborock/map/b01_q10_render.py
Comment thread roborock/map/b01_q10_map_parser.py Outdated
Comment thread roborock/map/b01_q10_map_parser.py Outdated
@hCoureau

Copy link
Copy Markdown
Contributor Author

@allenporter Thanks for the detailed feedback, and sorry I missed the earlier comments. Pushed cbd6abc and merged current main.

  • Clean-record maps now have a dedicated Q10CleanRecordMapPacket type; ordinary current/saved maps no longer carry historical_trace. The grid, rooms, erase zones, carpet and calibration are shared across all three map kinds, so those stay in the common base.
  • The renderer reads the historical path directly from the clean-record packet; callers only supply a separate trace for live maps. The consumer in feat: expose Q10 map archives #937 is updated too.
  • decode_message looks up the marker once, the LZ4 output bound is required, and the unused trace-parser return value is removed.

Validation: 999 tests and 92 snapshots passed, all pre-commit checks passed, and wheel/sdist builds passed. The dependent read-only PRs have been updated as well. Could you take another look when you have time, particularly at the shared-map/dedicated-clean-record type boundary?

These maintenance changes were prepared with OpenAI Codex assistance.

@allenporter allenporter left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for iterating on this and splitting out the clean-record path ownership.

Taking a close look at the resulting Q10CleanRecordMapPacket boundary, the **vars(packet) unpacking in parse_map_packet and the isinstance check in render_q10_map feel like an awkward fit for dataclass inheritance. Rather than subclassing Q10MapPacket, modeling this as a composite object Q10CleanRecordDetail(map=Q10MapPacket, trace=Q10HistoricalTracePacket | None) would be significantly cleaner and avoid both constructor duplication and isinstance branches in rendering.

I've also left a few inline comments on RoborockEnum fallback resilience, stripping stray origin points, and trimming internal wire fields from public models.

Comment thread roborock/map/b01_q10_map_parser.py Outdated
Comment thread roborock/map/b01_q10_map_parser.py Outdated
Comment thread roborock/map/b01_q10_map_parser.py Outdated
Comment thread roborock/map/b01_q10_map_parser.py Outdated
Comment thread roborock/map/b01_q10_map_parser.py Outdated
Comment thread roborock/map/b01_q10_render.py Outdated
@hCoureau

Copy link
Copy Markdown
Contributor Author

@allenporter Implemented the requested composition in 4eb0b9b and updated the consumers in #937–#939:

  • Q10CleanRecordDetail(map, trace) replaces map inheritance and **vars(packet) construction. Rendering uses the supplied map/path directly, without type-dependent branches or ignored arguments.
  • Q10MapPacketKind now has an explicit unknown member and constant-time lookup; unknown firmware markers are ignored.
  • Historical paths expose only points and heading; version validation stays internal and the opaque wire value is no longer public.
  • Removed the unused archive-marker and carpet-mask helpers.
  • Historical paths use the existing conservative stray-leading-point filter, with tests for the outlier, ordinary origin points, and short paths.

Merged current main and preserved the new position/zone/goto support. Full local validation on #936: 1349 passed, 53 existing xfailed, 92 snapshots passed; pre-commit and package builds passed.

Separately, current main's new model conformance test fails on the existing frozen Q10RoborockPoint. I reproduced that on untouched eac001c, opened #964, and submitted the isolated fix in #965. This branch includes that commit so validation can pass; #965 should land first.

Could you review the revised boundary and parser changes when you have time?

@lboue

lboue commented Sep 22, 2026 •

Copy link
Copy Markdown
Contributor

@hCoureau @allenporter This PR is really valuable for Q10 map support, but it's been waiting on the Sep 12 architecture feedback.

Do you want help picking up the composition refactor? The changes are clear:

  • Q10CleanRecordDetail(map, trace) composition model
  • RoborockEnum + enum resilience fixes
  • Cleanup (unused helpers, internal fields trimming)

@allenporter, should hCoureau tackle these all at once, or is there a staged approach you'd prefer?

Happy to pair on implementation or review if that unblocks things.

@hCoureau

Copy link
Copy Markdown
Contributor Author

Thanks — I’ve already implemented the full set of Sep 12 changes in 4eb0b9b, including the Q10CleanRecordDetail(map, trace) composition model, enum fallback handling, removal of unused helpers, internal-field cleanup, and the historical-trace filtering. I also updated the dependent consumers in #937–#939 and resolved the inline threads.
CI is green and the branch is ready for Allen’s follow-up review. If you have time to review the updated implementation too, that would be very helpful.

@allenporter allenporter left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you! I very much appreciate the hard work on this.

Comment thread tests/protocols/test_b01_q10_protocol.py
@allenporter
allenporter merged commit 14b4bc6 into Python-roborock:main Sep 27, 2026
7 checks passed
@hCoureau
hCoureau deleted the feat/q10-archive-packets branch September 27, 2026 15:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants